#ifndef FFPLAYER_H
#define FFPLAYER_H
#include "msg_queue.h"
#include "msg.h"
#include <thread>
#include <iostream>
#include <ffplay_stater.h>
/*
@brief 从packetqueue中获取数据包,进行解码后从接口中输出frame?或者写入framequeue中?可能只需要写
所以说需要的数据是,packetqueue , 和解码器上下文.
*/
class Decoder{
public:
    Decoder();
    ~Decoder();
    //是否有未处理包
    int decoder_reorder_pts = 0;
    int packet_pending_ = 0;
    PakcetQueue *pq_;
    AVPacket pkt_;
    //FrameQueue *fq;
    AVCodecContext *avcdx_;
    std::thread *decoder_thread_ = NULL;
//    int strat_time
    int serial_;
    int finished_;

    int64_t next_pts;
    AVRational next_pts_tb;
    int64_t start_pts;
    AVRational start_pts_tb;

    void decoder_init(PakcetQueue *pqm, AVCodecContext *ctx);
    int decoder_start(enum AVMediaType type,void *arg);

    int decoder_decode_frame(AVFrame *frame);

    int audio_thread(void *arg);
    int video_thread(void *arg);
    
};

class Clock{
public:
    Clock();

    int set_clock(double pts,double time );
    double get_clock();

    ~Clock();
private:
    double last_uplate;
    double pts;
    double drfme;
    double last_pts;
};

class FFPlayer
{
public:
    FFPlayer();
    int is_netstream=0;
    int ffp_create();
    int ffp_prepare_async_l(char *filename);

    int stream_open(char *filename);
    int stream_close();

    int stop_l();
    /*
    最主要目标创建一个decoder,


    */
    int stream_componnet_open(int stream_index);
    int stream_componnet_close(int stream_index);
    //打开audio输出
    int audio_open(int wanted_freq,int wanted_layerout,int wanted_nb_chennel ,AudioParams *tgt);
    //视频暑促
    int video_open();
    int read_thread();
//    int video_thread();
//    int vedio_thread();
//    int audio_thread();

    Buff audio_buff1 = {NULL,0};
    Buff audio_buff = {NULL,0};
    int buff_index=0;
    int paused=0;

    MessageQueue msg_queue_;
    //重采样上下文
    struct SwrContext *swr_ctx = NULL;//重采样上下文

    //包队列
    PakcetQueue audpq;
    PakcetQueue vidpq;
    //帧队列
    FrameQueue audfq;
    FrameQueue vidfq;
    //目标输出格式
    struct AudioParams audio_tgt;//目标输出格式
    struct AudioParams audio_src;//源输出格式
    int starttime;
    int seek=0;
    int eof=0;

    int abort_request = 0;

    int audio_stream = -1;
    int video_stream = -1;

    double audio_time_n;
    Clock master_clock;

    Decoder audcoder;
    Decoder videocoder;

    AVStream *st_audio = NULL;
    AVStream *st_video = NULL;

    int index_audio = -1;
    int index_video = -1;

    void refresh_thread();
    int video_refresh(double *re_time);
    std::function<int (const Frame*)> video_refresh_callback_ = NULL;
    void add_refresh_callback(std::function<int (const Frame*)> callback);
    AVFormatContext *avfmt;
//    (void*) refresh_callback();
private :
//    AVFormatContext *avfmt;
    char* input_filename_;


    std::thread *video_refresh_thread_;
    std::thread *read_thread_;

};
inline static void ffp_notify_msg1(FFPlayer *ffp, int what) {
    msg_queue_put_simple3(&ffp->msg_queue_, what, 0, 0);
}

inline static void ffp_notify_msg2(FFPlayer *ffp, int what, int arg1) {
    msg_queue_put_simple3(&ffp->msg_queue_, what, arg1, 0);
}

inline static void ffp_notify_msg3(FFPlayer *ffp, int what, int arg1, int arg2) {
    msg_queue_put_simple3(&ffp->msg_queue_, what, arg1, arg2);
}

inline static void ffp_notify_msg4(FFPlayer *ffp, int what, int arg1, int arg2, void *obj, int obj_len) {
    msg_queue_put_simple4(&ffp->msg_queue_, what, arg1, arg2, obj, obj_len);
}

inline static void ffp_remove_msg(FFPlayer *ffp, int what) {
    msg_queue_remove(&ffp->msg_queue_, what);
}
#endif // FFPLAYER_H
